<template>
  <view class="template-editor">
    <!-- 顶部工具栏 -->
    <view class="editor-toolbar">
      <view class="toolbar-left">
        <button class="tool-btn" @click="goBack"><uni-icons type="back" size="18" />返回</button>
        <button class="tool-btn" @click="saveTemplate"><uni-icons type="save" size="18" />保存</button>
      </view>
      <view class="toolbar-center">
        <button class="tool-btn" @click="addPhotoSlot"><uni-icons type="image" size="18" />添加照片槽</button>
        <button class="tool-btn" @click="addBackgroundImage"><uni-icons type="image" size="18" />添加背景图</button>
        <button class="tool-btn" @click="deleteElement"><uni-icons type="trash" size="18" />删除</button>
      </view>
      <view class="toolbar-right">
        <!-- 移除预览按钮 -->
      </view>
    </view>

    <!-- 主编辑区域 -->
    <view class="editor-main">
      <!-- 左侧画布区域 -->
      <view class="canvas-container" :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }">
        <view class="canvas-content" :style="{ transform: 'scale(' + scale + ')' }">
          <!-- 模板背景 -->
          <view class="template-background" 
                :style="{ width: templateData.width + 'px', height: templateData.height + 'px' }"
                @click.stop="handleBackgroundClick">
            <!-- 背景图片 -->
            <image v-for="(bg, index) in templateData.background_images" 
                   :key="'bg_' + index"
                   :src="bg.image_url"
                   class="background-image"
                   :style="{
                     left: bg.position_x + 'px',
                     top: bg.position_y + 'px',
                     width: bg.width + 'px',
                     height: bg.height + 'px',
                     zIndex: 1
                   }" />
            
            <!-- 照片槽位 -->
            <view v-for="(slot, index) in templateData.slots" 
                  :key="'slot_' + index"
                  class="photo-slot"
                  :class="{ 'selected': selectedElement === slot, 'dragging': isDragging && dragElement === slot }"
                  :style="{
                    left: slot.position_x + 'px',
                    top: slot.position_y + 'px',
                    width: slot.width + 'px',
                    height: slot.height + 'px',
                    backgroundColor: slotColors[(slot.photo_index - 1) % slotColors.length],
                    zIndex: 2
                  }"
                  @click.stop="selectElement(slot)"
                  @mousedown.stop="startDrag($event, slot)"
                  @touchstart.stop.prevent="startDrag($event, slot)">
              <text class="slot-number">{{slot.photo_index}}</text>
            </view>
          </view>
        </view>
      </view>

      <!-- 右侧属性面板 -->
      <view class="properties-panel">
        <view class="panel-section">
          <view class="section-title">模板属性</view>
          <view class="property-item">
            <text>名称：</text>
            <input type="text" v-model="templateData.name" placeholder="请输入模板名称" />
          </view>
          <view class="property-item">
            <text>宽度：</text>
            <input type="number" v-model="templateData.width" @change="updateTemplate" />
          </view>
          <view class="property-item">
            <text>高度：</text>
            <input type="number" v-model="templateData.height" @change="updateTemplate" />
          </view>
          <view class="property-item">
            <text>照片数：</text>
            <input type="number" v-model.number="templateData.photo_count" @change="updatePhotoCount" min="1" max="10" />
          </view>
          <view class="property-item">
            <text>排序：</text>
            <input type="number" v-model="templateData.sort" @change="updateTemplate" />
          </view>
          <view class="property-item">
            <text>状态：</text>
            <switch :checked="templateData.status === 1" @change="e => templateData.status = e.detail.value ? 1 : 0" />
          </view>
        </view>

        <!-- 添加背景图属性部分 -->
        <view class="panel-section" v-if="templateData.background_images.length > 0">
          <view class="section-title">背景图属性</view>
          <view v-for="(bg, index) in templateData.background_images" :key="'bg_prop_' + index" class="bg-image-item">
            <view class="bg-image-preview">
              <image :src="bg.image_url" mode="aspectFit" class="bg-thumbnail" />
            </view>
            <view class="property-item">
              <text>URL：</text>
              <input type="text" v-model="bg.image_url" placeholder="图片URL" />
            </view>
            <view class="property-item">
              <text>X坐标：</text>
              <input type="number" v-model.number="bg.position_x" @input="updateBackgroundImage(index)" />
            </view>
            <view class="property-item">
              <text>Y坐标：</text>
              <input type="number" v-model.number="bg.position_y" @input="updateBackgroundImage(index)" />
            </view>
            <view class="property-item">
              <text>宽度：</text>
              <input type="number" v-model.number="bg.width" @input="updateBackgroundImage(index)" />
            </view>
            <view class="property-item">
              <text>高度：</text>
              <input type="number" v-model.number="bg.height" @input="updateBackgroundImage(index)" />
            </view>
            <view class="button-group">
              <button class="mini-btn" @click="replaceBackgroundImage(index)">替换图片</button>
              <button class="mini-btn delete-btn" @click="deleteBackgroundImage(index)">删除</button>
            </view>
          </view>
        </view>

        <!-- 选中元素的属性编辑 -->
        <view v-if="selectedElement" class="panel-section">
          <view class="section-title">照片槽属性</view>
          <view class="property-item">
            <text>序号：</text>
            <input type="number" v-model.number="selectedElement.photo_index" @input="onPropertyChange" min="1" :max="templateData.photo_count" />
            <view class="color-indicator" :style="{ backgroundColor: slotColors[(selectedElement.photo_index - 1) % slotColors.length] }"></view>
          </view>
          <view class="property-item">
            <text>X坐标：</text>
            <input type="number" v-model.number="selectedElement.position_x" @input="onPropertyChange" min="0" :max="templateData.width - selectedElement.width" />
          </view>
          <view class="property-item">
            <text>Y坐标：</text>
            <input type="number" v-model.number="selectedElement.position_y" @input="onPropertyChange" min="0" :max="templateData.height - selectedElement.height" />
          </view>
          <view class="property-item">
            <text>宽度：</text>
            <input type="number" v-model.number="selectedElement.width" @input="onPropertyChange" min="50" :max="templateData.width - selectedElement.position_x" />
          </view>
          <view class="property-item">
            <text>高度：</text>
            <input type="number" v-model.number="selectedElement.height" @input="onPropertyChange" min="50" :max="templateData.height - selectedElement.position_y" />
          </view>
          <view class="hint-text">* 序号决定照片槽的颜色和照片顺序，序号范围：1-{{templateData.photo_count}}</view>
          
          <!-- 添加删除按钮 -->
          <view class="action-buttons">
            <button class="action-btn delete-btn" @click="deleteSelectedElement">删除照片槽</button>
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
const db = uniCloud.database()

export default {
  data() {
    return {
      templateId: '',
      templateData: {
        name: '',
        width: 1920,
        height: 2880,
        photo_count: 10, // 默认支持10个照片
        slots: [],
        background_images: [],
        thumbnail_url: '',
        status: 1,
        sort: 100,
        create_date: null
      },
      selectedElement: null,
      scale: 0.2, // 画布缩放比例
      canvasWidth: 800,
      canvasHeight: 1000,
      slotColors: [
        '#ff69b4', // 粉红色
        '#87ceeb', // 天蓝色
        '#90ee90', // 淡绿色
        '#ffa500', // 橙色
        '#9370db', // 紫色
        '#20b2aa', // 浅海洋绿
        '#ff6347', // 番茄色
        '#4682b4', // 钢青色
        '#7fff00', // 查特鲁斯绿色
        '#ff8c00'  // 深橙色
      ], // 10种不同的颜色对应10个序号
      isDragging: false,
      dragStartX: 0,
      dragStartY: 0,
      dragElement: null,
      dragStartPos: { x: 0, y: 0 },
      currentDragPos: { x: 0, y: 0 },
      animationFrameId: null,
      updateTimer: null, // 延迟更新计时器
    }
  },
  computed: {
    // 根据photo_index对slots进行分组
    groupedSlots() {
      const groups = {}
      this.templateData.slots.forEach(slot => {
        if (!groups[slot.photo_index]) {
          groups[slot.photo_index] = []
        }
        groups[slot.photo_index].push(slot)
      })
      return groups
    }
  },
  onLoad(options) {
    if (options.id) {
      this.templateId = options.id
      this.loadTemplateData()
    }
    // 计算合适的缩放比例
    this.calculateScale()
    
    // 绑定全局事件
    this.bindEvents()
  },
  onUnload() {
    // 解绑全局事件
    this.unbindEvents()
  },
  methods: {
    async loadTemplateData() {
      try {
        uni.showLoading({
          title: '加载中...',
          mask: true
        })
        
        // 查询模板详情
        const res = await db.collection('a-templates').doc(this.templateId).get()
        
        if (res.result.data && res.result.data.length > 0) {
          const templateData = res.result.data[0]
          
          // 更新模板数据
          this.templateData = {
            name: templateData.name || '',
            width: templateData.width || 1920,
            height: templateData.height || 2880,
            photo_count: templateData.photo_count || 10,
            slots: templateData.slots || [],
            background_images: templateData.background_images || [],
            thumbnail_url: templateData.thumbnail_url || '',
            status: templateData.status ?? 1,
            sort: templateData.sort || 100,
            create_date: templateData.create_date || new Date().getTime()
          }
          
          // 确保create_date是时间戳格式
          if (this.templateData.create_date && typeof this.templateData.create_date === 'string') {
            this.templateData.create_date = new Date(this.templateData.create_date).getTime()
          }
          
          // 重新计算缩放比例
          this.$nextTick(() => {
            this.calculateScale()
          })
          
          console.log('加载的模板数据:', this.templateData)
        } else {
          throw new Error('模板不存在')
        }
      } catch (e) {
        console.error('加载模板数据失败:', e)
        uni.showToast({
          title: '加载模板数据失败: ' + (e.message || '未知错误'),
          icon: 'none',
          duration: 3000
        })
      } finally {
        uni.hideLoading()
      }
    },
    calculateScale() {
      // 根据模板尺寸和画布尺寸计算合适的缩放比例
      const scaleX = (this.canvasWidth - 40) / this.templateData.width // 留出20px边距
      const scaleY = (this.canvasHeight - 40) / this.templateData.height
      this.scale = Math.min(scaleX, scaleY)
    },
    addPhotoSlot() {
      // 获取当前照片槽的索引分布情况
      const existingIndices = this.templateData.slots.map(s => s.photo_index || 0);
      
      // 找出缺失的最小索引（1到photo_count之间）
      let newPhotoIndex = 1;
      for (let i = 1; i <= this.templateData.photo_count; i++) {
        if (!existingIndices.includes(i)) {
          newPhotoIndex = i;
          break;
        }
      }
      
      // 如果所有索引都已存在，则默认使用1
      if (newPhotoIndex > this.templateData.photo_count) {
        newPhotoIndex = 1;
      }

      // 计算合理的初始位置 - 居中且不重叠
      const offsetX = this.templateData.slots.length * 30;
      const offsetY = this.templateData.slots.length * 30;
      
      const centerX = (this.templateData.width - 837) / 2 + offsetX % 200;
      const centerY = (this.templateData.height - 555) / 2 + offsetY % 200;
      
      const newSlot = {
        photo_index: newPhotoIndex,
        position_x: Math.max(0, Math.min(centerX, this.templateData.width - 837)),
        position_y: Math.max(0, Math.min(centerY, this.templateData.height - 555)),
        width: 837,
        height: 555
      };
      
      this.templateData.slots.push(newSlot);
      this.selectElement(newSlot);
      
      uni.showToast({
        title: `已添加照片槽 ${newPhotoIndex}`,
        icon: 'none',
        duration: 2000
      });
    },
    addBackgroundImage() {
      uni.chooseImage({
        count: 1,
        success: (res) => {
          const tempFilePath = res.tempFilePaths[0]
          
          // 上传图片到服务器
          this.uploadImage(tempFilePath, (uploadedUrl) => {
            const newBackground = {
              image_url: uploadedUrl,
              position_x: 0,
              position_y: 0,
              width: this.templateData.width,
              height: this.templateData.height
            }
            
            this.templateData.background_images.push(newBackground)
            
            uni.showToast({
              title: '背景图已添加',
              icon: 'none',
              duration: 2000
            })
          })
        },
        fail: () => {
          // 用户取消选择
        }
      })
    },
    selectElement(element) {
      // 只允许选择照片槽
      if (element && element.photo_index !== undefined) {
        this.selectedElement = element
      }
    },
    handleBackgroundClick(event) {
      // 判断点击的是否是背景本身，而不是其子元素
      if (event.target === event.currentTarget) {
        this.clearSelection();
      }
    },
    clearSelection() {
      this.selectedElement = null;
    },
    deleteElement() {
      if (!this.selectedElement) return

      // 只删除照片槽
      if (this.selectedElement.photo_index !== undefined) {
        const index = this.templateData.slots.findIndex(
          slot => slot === this.selectedElement
        )
        if (index > -1) {
          this.templateData.slots.splice(index, 1)
        }
        
        this.selectedElement = null
      }
    },
    updateElement() {
      if (!this.selectedElement) return;
      
      // 只更新照片槽
      if (this.selectedElement.photo_index !== undefined) {
        // 找到当前选中的元素在数组中的索引
        const index = this.templateData.slots.findIndex(
          slot => slot === this.selectedElement
        );
        
        if (index > -1) {
          // 确保所有数值属性都是数字类型
          const updatedSlot = {
            photo_index: Number(this.selectedElement.photo_index) || 1,
            position_x: Number(this.selectedElement.position_x) || 0,
            position_y: Number(this.selectedElement.position_y) || 0,
            width: Number(this.selectedElement.width) || 100,
            height: Number(this.selectedElement.height) || 100
          };
          
          // 边界检查
          if (updatedSlot.position_x < 0) updatedSlot.position_x = 0;
          if (updatedSlot.position_y < 0) updatedSlot.position_y = 0;
          if (updatedSlot.position_x + updatedSlot.width > this.templateData.width) {
            updatedSlot.position_x = this.templateData.width - updatedSlot.width;
          }
          if (updatedSlot.position_y + updatedSlot.height > this.templateData.height) {
            updatedSlot.position_y = this.templateData.height - updatedSlot.height;
          }
          
          // 确保photo_index在有效范围内
          if (updatedSlot.photo_index < 1) {
            updatedSlot.photo_index = 1;
          }
          if (updatedSlot.photo_index > this.templateData.photo_count) {
            updatedSlot.photo_index = this.templateData.photo_count;
          }
          
          // Vue 3方式更新数组元素
          // 创建新数组并替换
          const updatedSlots = [...this.templateData.slots];
          updatedSlots[index] = updatedSlot;
          this.templateData.slots = updatedSlots;
          
          // 更新选中的元素引用
          this.selectedElement = updatedSlot;
        }
      }
    },
    handleKeydown(event) {
      if (!this.selectedElement) return
      
      const step = event.shiftKey ? 10 : 1
      
      // 只为照片槽启用键盘快捷键
      if (this.selectedElement.photo_index !== undefined) {
        switch(event.key) {
          case 'ArrowLeft':
            this.selectedElement.position_x -= step
            break
          case 'ArrowRight':
            this.selectedElement.position_x += step
            break
          case 'ArrowUp':
            this.selectedElement.position_y -= step
            break
          case 'ArrowDown':
            this.selectedElement.position_y += step
            break
          case 'Delete':
            this.deleteElement()
            break
        }
        
        this.updateElement()
      }
    },
    async saveTemplate() {
      try {
        uni.showLoading({
          title: '保存中...',
          mask: true
        })
        
        // 保存前更新选中元素以确保最新更改已应用
        if (this.selectedElement) {
          this.updateElement()
        }
        
        // 检查所有照片槽是否有效
        const validTemplateData = this.validateTemplate()
        if (!validTemplateData) {
          return
        }
        
        // 创建一个新的对象，只包含需要更新的字段
        const templateData = {
          name: validTemplateData.name,
          width: Number(validTemplateData.width),
          height: Number(validTemplateData.height),
          photo_count: Number(validTemplateData.photo_count),
          slots: validTemplateData.slots,
          background_images: validTemplateData.background_images,
          thumbnail_url: validTemplateData.thumbnail_url || '',
          status: Number(validTemplateData.status),
          sort: Number(validTemplateData.sort)
        }
        
        // 添加更新时间
        templateData.update_date = new Date().getTime()
        
        if (this.templateId) {
          // 更新已有模板 - 正确使用doc方法指定要更新的文档
          console.log('准备更新模板:', this.templateId, templateData)
          const res = await db.collection('a-templates').where({_id: this.templateId}).update(templateData)
          console.log('模板已更新:', res)
        } else {
          // 新建模板
          templateData.create_date = new Date().getTime()
          const res = await db.collection('a-templates').add(templateData)
          this.templateId = res.id
          console.log('新模板已创建:', res)
        }
        
        uni.showToast({
          title: '保存成功',
          icon: 'success',
          duration: 2000
        })
      } catch (e) {
        console.error('保存失败:', e)
        uni.showToast({
          title: '保存失败: ' + (e.message || '未知错误'),
          icon: 'none',
          duration: 3000
        })
      } finally {
        uni.hideLoading()
      }
    },
    goBack() {
      // 提醒用户保存更改
      if (this.hasUnsavedChanges()) {
        uni.showModal({
          title: '提示',
          content: '您有未保存的更改，确定要离开吗？',
          success: (res) => {
            if (res.confirm) {
              uni.navigateBack()
            }
          }
        })
      } else {
        uni.navigateBack()
      }
    },
    previewTemplate() {
      // 实现模板预览功能
    },
    onReady() {
      // 设置画布尺寸为容器大小
      const query = uni.createSelectorQuery().in(this)
      query.select('.canvas-container').boundingClientRect(data => {
          if (data) {
          this.canvasWidth = data.width
          this.canvasHeight = data.height
          this.calculateScale()
        }
      }).exec()
    },
    bindEvents() {
      // 绑定键盘事件
      window.addEventListener('keydown', this.handleKeydown)
      
      // 绑定鼠标事件（使用passive:false允许我们取消默认行为）
      window.addEventListener('mousemove', this.handleMouseMove, { passive: false })
      window.addEventListener('mouseup', this.handleMouseUp, { passive: false })
      
      // 触摸事件支持
      window.addEventListener('touchmove', this.handleTouchMove, { passive: false })
      window.addEventListener('touchend', this.handleMouseUp, { passive: false })
    },
    
    unbindEvents() {
      window.removeEventListener('keydown', this.handleKeydown)
      window.removeEventListener('mousemove', this.handleMouseMove)
      window.removeEventListener('mouseup', this.handleMouseUp)
      window.removeEventListener('touchmove', this.handleTouchMove)
      window.removeEventListener('touchend', this.handleMouseUp)
      
      // 清除可能的动画帧
      if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId)
        this.animationFrameId = null
      }
      
      // 清除属性更新计时器
      if (this.updateTimer) {
        clearTimeout(this.updateTimer)
        this.updateTimer = null
      }
    },

    startDrag(event, element) {
      // 只允许拖拽照片槽
      if (!element || element.photo_index === undefined) return
      
      // 防止默认行为和冒泡
      event.stopPropagation()
      event.preventDefault()
      
      // 开始拖动
      this.isDragging = true
      this.dragElement = element
      
      // 记录起始位置
      if (event.type.startsWith('touch')) {
        this.dragStartX = event.touches[0].clientX
        this.dragStartY = event.touches[0].clientY
      } else {
        this.dragStartX = event.clientX
        this.dragStartY = event.clientY
      }
      
      // 记录元素原始位置
      this.dragStartPos = {
        x: element.position_x,
        y: element.position_y
      }
      
      // 初始化当前拖动位置
      this.currentDragPos = { ...this.dragStartPos }
      
      // 选中当前元素
      this.selectElement(element)
      
      // 启动动画帧渲染
      this.startDragAnimation()
    },
    
    // 鼠标移动处理 - 只更新当前位置，不渲染
    handleMouseMove(event) {
      if (!this.isDragging || !this.dragElement) return
      
      event.preventDefault()
      
      let currentX = event.clientX
      let currentY = event.clientY
      
      this.updateDragPosition(currentX, currentY)
    },
    
    // 触摸移动处理
    handleTouchMove(event) {
      if (!this.isDragging || !this.dragElement) return
      
      event.preventDefault()
      
      let currentX = event.touches[0].clientX
      let currentY = event.touches[0].clientY
      
      this.updateDragPosition(currentX, currentY)
    },
    
    // 更新拖动位置
    updateDragPosition(currentX, currentY) {
      // 计算位移（考虑缩放比例）
      const deltaX = (currentX - this.dragStartX) / this.scale
      const deltaY = (currentY - this.dragStartY) / this.scale
      
      // 计算新位置
      let newX = Math.round(this.dragStartPos.x + deltaX)
      let newY = Math.round(this.dragStartPos.y + deltaY)
      
      // 边界检查
      if (newX < 0) newX = 0
      if (newY < 0) newY = 0
      if (newX + this.dragElement.width > this.templateData.width) {
        newX = this.templateData.width - this.dragElement.width
      }
      if (newY + this.dragElement.height > this.templateData.height) {
        newY = this.templateData.height - this.dragElement.height
      }
      
      // 更新当前拖动位置（不直接修改元素，由动画帧负责渲染）
      this.currentDragPos = {
        x: newX,
        y: newY
      }
    },
    
    // 启动拖拽动画
    startDragAnimation() {
      // 确保没有多余的动画帧
      if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId)
      }
      
      // 创建拖动元素的副本以免直接修改原对象
      const dragElementCopy = { ...this.dragElement };
      
      // 动画渲染函数
      const animateDrag = () => {
        if (!this.isDragging) return
        
        // 更新元素位置 - 仅在视图上更新，不修改原始数据
        if (this.dragElement) {
          this.dragElement.position_x = this.currentDragPos.x;
          this.dragElement.position_y = this.currentDragPos.y;
        }
        
        // 继续下一帧
        this.animationFrameId = requestAnimationFrame(animateDrag)
      }
      
      // 启动动画
      this.animationFrameId = requestAnimationFrame(animateDrag)
    },
    
    // 鼠标抬起处理
    handleMouseUp(event) {
      if (!this.isDragging) return
      
      if (event) {
        event.preventDefault()
      }
      
      // 停止拖动
      this.isDragging = false
      
      // 停止动画
      if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId)
        this.animationFrameId = null
      }
      
      // 更新元素数据，确保保存
      if (this.dragElement) {
        // 创建新对象而不是直接修改
        const updatedElement = { ...this.dragElement };
        
        // 边界检查
        if (updatedElement.position_x < 0) updatedElement.position_x = 0;
        if (updatedElement.position_y < 0) updatedElement.position_y = 0;
        if (updatedElement.position_x + updatedElement.width > this.templateData.width) {
          updatedElement.position_x = this.templateData.width - updatedElement.width;
        }
        if (updatedElement.position_y + updatedElement.height > this.templateData.height) {
          updatedElement.position_y = this.templateData.height - updatedElement.height;
        }
        
        // 找到当前拖动的元素在数组中的索引
        const index = this.templateData.slots.findIndex(
          slot => slot === this.dragElement
        );
        
        if (index > -1) {
          // Vue 3方式更新数组元素
          const updatedSlots = [...this.templateData.slots];
          updatedSlots[index] = updatedElement;
          this.templateData.slots = updatedSlots;
          
          // 更新选中元素的引用
          if (this.selectedElement === this.dragElement) {
            this.selectedElement = updatedElement;
          }
        }
        
        this.dragElement = null;
      }
    },

    updateTemplate() {
      // 在模板属性改变时重新计算缩放
      this.calculateScale()
    },

    // 属性变更时实时更新元素
    onPropertyChange(event) {
      // 如果修改的是序号，确保范围在1到photo_count之间
      if (this.selectedElement && this.selectedElement.photo_index !== undefined) {
        if (this.selectedElement.photo_index < 1) {
          this.selectedElement.photo_index = 1;
        } else if (this.selectedElement.photo_index > this.templateData.photo_count) {
          this.selectedElement.photo_index = this.templateData.photo_count;
        }
      }
      
      // 直接更新，不使用延迟
      this.updateElement();
    },

    // 验证模板数据
    validateTemplate() {
      // 检查名称
      if (!this.templateData.name.trim()) {
        uni.showToast({
          title: '请输入模板名称',
          icon: 'none',
          duration: 2000
        })
        return null
      }
      
      // 检查尺寸
      if (this.templateData.width <= 0 || this.templateData.height <= 0) {
        uni.showToast({
          title: '请设置有效的模板尺寸',
          icon: 'none',
          duration: 2000
        })
        return null
      }
      
      // 检查照片槽
      if (this.templateData.slots.length === 0) {
          uni.showToast({
          title: '请至少添加一个照片槽',
          icon: 'none',
          duration: 2000
        })
        return null
      }
      
      // 确保所有照片槽的属性都是合法数值
      const validatedSlots = this.templateData.slots.map(slot => ({
        photo_index: Number(slot.photo_index) || 1,
        position_x: Number(slot.position_x) || 0,
        position_y: Number(slot.position_y) || 0,
        width: Number(slot.width) || 100,
        height: Number(slot.height) || 100
      }))
      
      // 确保所有背景图的属性都是合法数值
      const validatedBgImages = this.templateData.background_images.map(bg => ({
        image_url: bg.image_url || '',
        position_x: Number(bg.position_x) || 0,
        position_y: Number(bg.position_y) || 0,
        width: Number(bg.width) || 100,
        height: Number(bg.height) || 100
      }))
      
      // 确保create_date是时间戳格式
      let createDate = this.templateData.create_date
      if (typeof createDate === 'string') {
        createDate = new Date(createDate).getTime()
      } else if (!createDate) {
        createDate = new Date().getTime()
      }
      
      // 返回有效的模板数据
      return {
        ...this.templateData,
        slots: validatedSlots,
        background_images: validatedBgImages,
        create_date: createDate
      }
    },

    // 检查是否有未保存的更改
    hasUnsavedChanges() {
      // 简单实现，实际应考虑比较原始数据和当前数据
      return this.templateData.slots.length > 0 || this.templateData.background_images.length > 0
    },

    // 背景图属性编辑相关方法
    updateBackgroundImage(index) {
      if (index < 0 || index >= this.templateData.background_images.length) return
      
      // 确保所有数值属性都是数字类型
      const bg = this.templateData.background_images[index]
      
      bg.position_x = Number(bg.position_x) || 0
      bg.position_y = Number(bg.position_y) || 0
      bg.width = Number(bg.width) || 100
      bg.height = Number(bg.height) || 100
      
      // 边界检查
      if (bg.position_x < 0) bg.position_x = 0
      if (bg.position_y < 0) bg.position_y = 0
      if (bg.position_x + bg.width > this.templateData.width) {
        bg.position_x = this.templateData.width - bg.width
      }
      if (bg.position_y + bg.height > this.templateData.height) {
        bg.position_y = this.templateData.height - bg.height
      }
      
      // 创建新数组并替换，触发视图更新
      const updatedBackgrounds = [...this.templateData.background_images]
      updatedBackgrounds[index] = bg
      this.templateData.background_images = updatedBackgrounds
    },
    
    replaceBackgroundImage(index) {
      if (index < 0 || index >= this.templateData.background_images.length) return
      
      // 使用uni.chooseImage选择图片
      uni.chooseImage({
        count: 1,
        success: (res) => {
          const tempFilePath = res.tempFilePaths[0]
          
          // 上传图片到服务器
          this.uploadImage(tempFilePath, (uploadedUrl) => {
            // 更新背景图URL
            const bg = this.templateData.background_images[index]
            bg.image_url = uploadedUrl
            
            // 创建新数组并替换，触发视图更新
            const updatedBackgrounds = [...this.templateData.background_images]
            updatedBackgrounds[index] = bg
            this.templateData.background_images = updatedBackgrounds
          })
        }
      })
    },
    
    deleteBackgroundImage(index) {
      if (index < 0 || index >= this.templateData.background_images.length) return
      
          uni.showModal({
        title: '确认删除',
        content: '确定要删除这张背景图吗？',
        success: (res) => {
          if (res.confirm) {
            // 从数组中删除该背景图
            this.templateData.background_images.splice(index, 1)
          }
        }
      })
    },
    
    // 图片上传辅助方法
    uploadImage(filePath, callback) {
        uni.showLoading({
        title: '上传中...',
          mask: true
        })
      
      // 安全地获取文件扩展名
      const getFileExtension = (path) => {
        if (!path) return '.png'; // 默认扩展名
        const lastDotIndex = path.lastIndexOf('.');
        return lastDotIndex !== -1 ? path.substring(lastDotIndex) : '.png';
      };
      
      const fileExtension = getFileExtension(filePath);
      const cloudPath = 'template-images/' + Date.now() + '_' + Math.floor(Math.random() * 1000) + fileExtension;
      
      // 使用uniCloud.uploadFile上传到云存储
      uniCloud.uploadFile({
        filePath: filePath,
        cloudPath: cloudPath,
        onUploadProgress: (progressEvent) => {
          console.log('上传进度：' + Math.round(progressEvent.loaded * 100 / progressEvent.total) + '%')
        },
        success: (res) => {
          uni.hideLoading()
          
          // 获取上传后的文件链接
          const fileID = res.fileID
          
          // 将fileID转换为可访问的URL
          uniCloud.getTempFileURL({
            fileList: [fileID],
            success: (res) => {
              const tempFileURL = res.fileList[0].tempFileURL
              
              if (typeof callback === 'function') {
                callback(tempFileURL)
              }
              
              uni.showToast({
                title: '上传成功',
                icon: 'success',
                duration: 2000
              })
            },
            fail: (err) => {
              console.error('获取临时链接失败:', err)
              
              // 上传成功但获取临时链接失败，直接使用fileID
              if (typeof callback === 'function') {
                callback(fileID)
              }
              
              uni.showToast({
                title: '获取链接失败',
                icon: 'none',
                duration: 2000
              })
            }
          })
        },
        fail: (err) => {
          uni.hideLoading()
          console.error('上传失败:', err)
          
          uni.showToast({
            title: '上传失败: ' + (err.message || '未知错误'),
            icon: 'none',
            duration: 3000
          })
        }
      })
    },

    updatePhotoCount() {
      // 确保photo_count在1-10范围内
      if (this.templateData.photo_count < 1) {
        this.templateData.photo_count = 1;
      } else if (this.templateData.photo_count > 10) {
        this.templateData.photo_count = 10;
      }
      
      // 确保photo_count是整数
      this.templateData.photo_count = Math.floor(this.templateData.photo_count);
      
      // 调整所有超出新照片数量范围的照片槽
      if (this.templateData.slots && this.templateData.slots.length > 0) {
        let needsUpdate = false;
        
        // 创建新数组进行更新
        const updatedSlots = this.templateData.slots.map(slot => {
          // 如果photo_index超出当前photo_count，调整为最大允许值
          if (slot.photo_index > this.templateData.photo_count) {
            needsUpdate = true;
            return {
              ...slot,
              photo_index: this.templateData.photo_count
            };
          }
          return slot;
        });
        
        // 如果有更新，替换slots数组
        if (needsUpdate) {
          this.templateData.slots = updatedSlots;
          
          // 如果当前选中的元素序号超出范围，也需要更新
          if (this.selectedElement && this.selectedElement.photo_index > this.templateData.photo_count) {
            this.selectedElement.photo_index = this.templateData.photo_count;
          }
          
          uni.showToast({
            title: '已自动调整部分照片槽序号',
            icon: 'none',
            duration: 2000
          });
        }
      }
      
      // 重新计算视图比例
      this.updateTemplate();
    },

    deleteSelectedElement() {
      if (!this.selectedElement) return;
      
      uni.showModal({
        title: '确认删除',
        content: `确定要删除这个照片槽吗？（序号: ${this.selectedElement.photo_index}）`,
        success: (res) => {
          if (res.confirm) {
            this.deleteElement();
            uni.showToast({
              title: '照片槽已删除',
              icon: 'none',
              duration: 2000
            });
          }
        }
      });
    },
    }
  }
</script>

<style>
.template-editor {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background-color: #f5f5f5;
}

.editor-toolbar {
  display: flex;
  justify-content: space-between;
  padding: 10px;
  background-color: #ffffff;
  border-bottom: 1px solid #eaeaea;
}

.toolbar-left,
.toolbar-center,
.toolbar-right {
  display: flex;
  gap: 10px;
}

.tool-btn {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  background-color: #ffffff;
  font-size: 14px;
  cursor: pointer;
}

.tool-btn:hover {
  background-color: #f5f7fa;
}

.editor-main {
  flex: 1;
  display: flex;
  overflow: hidden;
}

.canvas-container {
  flex: 1;
  position: relative;
  overflow: auto;
  background-color: #e0e0e0;
  display: flex;
  justify-content: center;
  align-items: center;
}

.canvas-content {
  position: relative;
  transform-origin: center center;
}

.template-background {
  background-color: #ffffff;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  position: relative;
}

.background-image {
  position: absolute;
  pointer-events: none; /* 禁用鼠标事件 */
}

.photo-slot {
  position: absolute;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: move;
  user-select: none;
  touch-action: none; /* 防止触摸设备的默认行为 */
  transition: box-shadow 0.2s ease, transform 0.1s ease;
  border: 1px dashed rgba(255, 255, 255, 0.5);
  box-sizing: border-box;
}

.photo-slot:hover {
  outline: 1px dashed #67c23a;
}

.photo-slot.selected {
  outline: 2px solid #409eff;
  z-index: 10 !important;
  box-shadow: 0 0 8px rgba(64, 158, 255, 0.6);
}

.photo-slot.dragging {
  opacity: 0.7;
  box-shadow: 8px 8px 15px rgba(0, 0, 0, 0.35);
  z-index: 100 !important;
  cursor: grabbing;
  transform: scale(1.02);
  outline: 2px solid #67c23a;
}

.slot-number {
  font-size: 48px;
  color: #ffffff;
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
}

.properties-panel {
  width: 300px;
  background-color: #ffffff;
  border-left: 1px solid #eaeaea;
  padding: 20px;
  overflow-y: auto;
}

.panel-section {
  margin-bottom: 20px;
}

.section-title {
  font-size: 16px;
  font-weight: bold;
  margin-bottom: 10px;
  color: #333;
}

.property-item {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}

.property-item text {
  width: 60px;
  color: #666;
}

.property-item input {
  flex: 1;
  padding: 5px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}

.shortcut-list {
  color: #666;
  font-size: 14px;
}

.shortcut-item {
  margin-bottom: 5px;
}

.bg-image-item {
  margin-bottom: 20px;
  padding: 15px;
  border: 1px solid #eaeaea;
  border-radius: 4px;
  background-color: #f9f9f9;
}

.bg-image-preview {
  margin-bottom: 10px;
  display: flex;
  justify-content: center;
}

.bg-thumbnail {
  width: 200px;
  height: 100px;
  object-fit: contain;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  background-color: #fff;
}

.button-group {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
}

.mini-btn {
  font-size: 12px;
  padding: 5px 10px;
  flex: 1;
  margin: 0 5px;
}

.delete-btn {
  background-color: #f56c6c;
  color: white;
}

.color-indicator {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  margin-left: 5px;
}

.hint-text {
  font-size: 12px;
  color: #909399;
}

.action-buttons {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}

.action-btn {
  font-size: 12px;
  padding: 5px 10px;
  background-color: #f56c6c;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
</style>
